﻿// -------------------------------------------------------------------------
//    @FileName         :    NFCitySession.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-12
//    @Email			:    445267987@qq.com
//    @Module           :    NFCitySession
//    @Desc             :
//
// -------------------------------------------------------------------------

#include "NFCitySession.h"
#include "NFCityPlayer.h"
#include "NFCityPlayerUtil.h"
#include "NFCitySessionUtil.h"
#include "proto_access2zone.nanopb.h"
#include "NFServerComm/NFServerCommon/NFIServerMessageModule.h"

NFCitySession::NFCitySession()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFCitySession::~NFCitySession()
{
}

int NFCitySession::CreateInit()
{
    m_iPlayerObjID = 0;
    m_pPlayer = nullptr;

    m_iLoginChannel = 0;
    m_bClientVersionFlag = 0;
    m_tDelayStopTime = 0;

    m_bBusy = false;

    m_wClientSeq = 0;
    m_wServerSeq = 1;

    m_bPreRegist = false;
    m_iLoginPri = 0;
    m_iLoginZoneID = 0;

    m_bIsLogin = false;

    m_bIsRecruit = false;
    m_bAndriodCounted = false;
    m_bIOSCounted = false;
    m_iZoneAreaID = 0;
    m_bindulge = false;
    m_isRealName = false;
    m_isWillDelete = false;

    m_bLoginQueue = false;

    SetTimer(500, 0, 0, 0, 0, 0);
    return 0;
}

int NFCitySession::ResumeInit()
{
    m_pPlayer = nullptr;
    return 0;
}

int NFCitySession::OnTimer(int timeId, int callCount)
{
    Tick();
    return 0;
}

int NFCitySession::Tick()
{
    if( 0 != GetLastActiveTime() && GetLastActiveTime() + 300 < NF_ADJUST_TIMENOW() )
    {
        SendConndStop();
        DisConnect(SESSION_DISCONN_HEARTBEAT_TIMEOUT, proto_ff::ERR_CODE_ROLE_KICKOFF_HEARTBEAT_TIMEOUT);
    }
    return 0;
}

// Connect to the server, no return value indicates the operation is asynchronous
int NFCitySession::Connect(NFConnectionInfo* pstConnInfo)
{
    CHECK_NULL(0, pstConnInfo);
    SetConnInfo(pstConnInfo);
    m_stClientInfo.plat_type = (Proto_PlatType)m_stConnInfo.m_iDeviceType;
    if (!m_bAndriodCounted && !m_bIOSCounted)
    {
        switch (m_stClientInfo.plat_type)
        {
            case proto_ff::E_PLAT_ANDROID:
                m_bAndriodCounted = true;
                break;
            case proto_ff::E_PLAT_IOS:
                m_bIOSCounted = true;
                break;
            default:
                break;
        }
    }

    NFLogInfo(NF_LOG_DEFAULT, 0, " connect from {}, objid:", pstConnInfo->ShortDebugString(), GetGlobalId());

    //return message needed
    SetLastActiveTime(NF_ADJUST_TIMENOW());
    return 0;
}

int NFCitySession::Connect(const proto_ff::NFConnectionInfo* pstConnInfo)
{
    NFConnectionInfo conn;
    conn.FromPb(*pstConnInfo);
    return Connect(&conn);
}

// Disconnect from the server, parameter iType indicates the type of disconnection, iReason indicates the reason
int NFCitySession::DisConnect(int iType, int iReason)
{
    NFCityPlayer* pPlayer = GetPlayer();
    if (pPlayer && pPlayer->GetClientSessionID() == GetGlobalId())
    {
        NFCityPlayerUtil::OfflinePlayer(pPlayer);
    }

    NFCitySessionUtil::DeleteSession(this);
    return 0;
}

int NFCitySession::CloseConnect()
{
    LOG_INFO(m_iPlayerObjID, "server close connect,sessionid:", GetGlobalId());

    DisConnect(SESSION_DISCONN_FROM_SERVER, proto_ff::ERR_CODE_ROLE_KICKOFF_HEARTBEAT_TIMEOUT);
    return 0;
}

// Get the device type, the return value is the device type code
int32_t NFCitySession::GetDeviceType() const
{
    return m_stConnInfo.m_iDeviceType;
}

// Get the zone ID, return value is the zone ID
int NFCitySession::GetZoneID()
{
    if (0 != m_iZoneAreaID)
    {
        return NFServerIDUtil::GetZoneIDFromZoneAreaID(m_iZoneAreaID);
    }
    else
    {
        return NFGlobalSystem::Instance()->GetGlobalPluginManager()->GetZoneID();
    }
}

// Initialize client information based on the login request
void NFCitySession::InitClientInfoByLoginReq(const proto_ff::Proto_CSLoginReq* pLoginReq)
{
    m_stClientInfo.FromPb(pLoginReq->client_info());
    if (m_stConnInfo.m_szOpenID.empty())
    {
        m_stConnInfo.m_szOpenID = pLoginReq->account_id().c_str();
    }
    m_stClientInfo.plat_type = (Proto_PlatType)m_stConnInfo.m_iDeviceType;

    m_iLoginPri = pLoginReq->login_pri();
    m_iLoginZoneID = pLoginReq->zone_id();
}

// Get debug information, the return value is the debug information string
std::string NFCitySession::GetDebugInfo() const
{
    return "";
}

// Bind a player to the session, the return value is 0 for success
int NFCitySession::BindPlayer(NFCityPlayer* pPlayer)
{
    if (pPlayer)
    {
        m_iPlayerObjID = pPlayer->GetGlobalId();
        m_pPlayer = pPlayer;
    }
    else
    {
        m_iPlayerObjID = INVALID_ID;
        m_pPlayer = pPlayer;
    }

    return 0;
}

// Get the player object bound to the session
NFCityPlayer* NFCitySession::GetPlayer()
{
    if (m_pPlayer)
    {
        return m_pPlayer;
    }

    m_pPlayer = NFCityPlayer::GetObjByGlobalId(m_iPlayerObjID);

    return m_pPlayer;
}

// Get the active player object in the session
NFCityPlayer* NFCitySession::GetActivePlayer()
{
    //m_pPlayer = NFPlayerUtil::GetActivePlayer(m_iPlayerObjID);

    return m_pPlayer;
}

// Activate the session and check the message, the return value is the result of the check
int NFCitySession::ActiveAndCheck(uint16_t wMsgId, uint8_t bSubMsgId, uint32_t activeTime, uint16_t wClientSeq)
{
    SetLastActiveTime(activeTime);
    return 0;
}

// Handle the login process, the parameter is the login request information
int NFCitySession::Login(const proto_ff::Proto_CSLoginReq* pLoginReq)
{
    m_stConnInfo.m_bWorldType = NFGlobalSystem::Instance()->GetGlobalPluginManager()->GetWorldID(); // 不检验，玩家身上的worldtype就等于登录服务器配置的worldtype
    InitClientInfoByLoginReq(pLoginReq);

    m_bIsLogin = true;

    return 0;
}

int NFCitySession::Login(const proto_ff::Proto_LoginClientInfo* pClientInfo, int loginPri, int loginZoneId)
{
    m_stConnInfo.m_bWorldType = NFGlobalSystem::Instance()->GetGlobalPluginManager()->GetWorldID(); // 不检验，玩家身上的worldtype就等于登录服务器配置的worldtype
    m_stClientInfo.FromPb(*pClientInfo);
    m_stClientInfo.plat_type = (Proto_PlatType)m_stConnInfo.m_iDeviceType;

    m_iLoginPri = loginPri;
    m_iLoginZoneID = loginZoneId;

    m_bIsLogin = true;

    return 0;
}

// Get the player's role ID
uint64_t NFCitySession::GetRoleId()
{
    auto pPlayer = GetPlayer();
    if (pPlayer)
    {
        return pPlayer->GetRoleID();
    }

    return 0;
}

int NFCitySession::CheckPkgRate(int msg_id)
{
    //CHECK_EXPR_RETURN(NFLogicConfig::Instance()->IsPacketRateCheck());

    int count = 0;
    int interval = 0;
    uint64_t roleID = 0;
    if (m_pPlayer)
    {
        roleID = m_pPlayer->GetRoleID();
    }

    m_stPkgMng.AddPkgStatistic(msg_id, roleID, m_stConnInfo.m_ullUin);
    int ret = m_stPkgMng.CheckPkgRate(msg_id, count, interval);
    if (ret)
    {
        LOGSVR_FATAL("pkg check and kick player:" << roleID << " uin:" << m_stConnInfo.m_ullUin << " openid:" << GetAccountID() << " msgID:" << msg_id << " count:" << count << " interval:" << interval << " ret:" << ret);
        if (m_pPlayer)
        {
            //NFPlayerUtil::KickPlayer(m_pPlayer, proto_ff::ERR_CODE_SEND_PACKET_FREQUENCY_FAST);
        }
        else
        {
            int iRetCode = SendConndStop();
            if (iRetCode)
                DisConnect(SESSION_DISCONN_FROM_SERVER, SESSION_DISCONN_MSG_MONITOR);
        }

        return -1;
    }

    return 0;
}

bool NFCitySession::IsFromQQGameCenter()
{
    return false;
}

bool NFCitySession::IsFromWXGameCenter()
{
    return false;
}

int NFCitySession::CloneSessionSeq(NFCitySession* pSession)
{
    CHECK_NULL(0, pSession);

    m_wClientSeq = pSession->GetClientSeq();
    m_wServerSeq = pSession->GetServerSeq();

    return 0;
}

int NFCitySession::OnPreRegist(bool bSet)
{
    m_bPreRegist = bSet;

    return 0;
}

void NFCitySession::SetWillDelete()
{
    m_iPlayerObjID = 0;
    m_pPlayer = nullptr;
    m_isWillDelete = true;
}

int NFCitySession::Check(uint16_t wMsgId, timeval* pstTimeStamp, uint16_t wClientSeq)
{
    return 0;
}

int NFCitySession::SendConndStop()
{
    return FindModule<NFIServerMessageModule>()->SendMsgToProxyServer(NF_ST_CITY_SERVER, GetConnBusId(), E_ACCESS2ZONE_STOP, proto_ff::Zone2AccessStop(), GetConnIndex());
}
